"""
GUI编程和tkinter介绍-第一个GU程序
PEP8编码规范-窗口大小和位置
GU编程整体描述-常用组件汇总
GU程序的经典面向对象写法
Label组件-tkinter中图像正确显示全局变量写法
options选项详解-底层源码分析和阅读-可变参数和运算符重载复习
Button-anchor位置控制
Entry-StringVar-登录界面设计和功实现
Text多行文本框详解-复杂tag标记
Radiobutton-Checkbuttoni详解
Canvasl画布组件
Grid布局管理器详解
计算器软件界面的设计
Pack布局管理器-钢琴软件界面设计
Place管理器-绝对位置和相对位置
扑克游戏界面设计-增加事件操作
lambda表达式-事件传参应用
三种事件绑定方式总结
optionmenu选项菜单-scale滑块
颜色框-文件选择框-读取文件内容
简单对话框-通用消息框-ttk子模块问题
主菜单-上下文菜单
"""
# from tkinter import *
# from tkinter import messagebox
#
# # 创建应用程序主窗口对象（也称：根窗口）
# root = Tk()
# # 在主窗口中，添加各种可视化组件，比如：按钮（Button）、文本框（Label）等。
# btn01 = Button(root)
# btn01["text"] = "点击送花"
# # 通过几何布局管理器，管理组件的大小和位置
# btn01.pack()
#
#
# # 事件处理
# def songhua(e):  # e就是事件对象
#     messagebox.showinfo("Message", "送你花")
#     print("送花")
#
#
# btn01.bind("<Button-1>", songhua)
#
# root.mainloop()  # 调用组件的mainloop()方法，进入事件循环

# from tkinter import *
#
# root = Tk()
# root.title("测试主窗口的位置和大小")
# root.geometry("500x400+100+200")  # 宽度 500，高度 400；距屏幕左边 100，距屏幕上边200
# root.mainloop()

# # 测试一个经典的GUI程序的写法，使用面向对象的方式
# from tkinter import *
# from tkinter import messagebox
#
# class Application(Frame):
#     """一个经典的GUI程序类的写法"""
#
#     def __init__(self, master):
#         super().__init__(master)  # super代表的是父类的定义，而不是父类对象
#         self.master = master
#         # 几何布局管理器，管理组件的大小和位置
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         """创建组件"""
#         self.btn01 = Button(self)
#         self.btn01["text"] = "点击送花"
#         self.btn01.pack()
#         self.btn01["command"] = self.songhua
#         # 创建一个退出按钮
#         self.btnQuit = Button(self, text="退出", command=root.destroy)
#         # 将组件放入application里
#         self.btnQuit.pack()
#
#     def songhua(self):
#         messagebox.showinfo("送花", "送你花")
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("400x100+200+300")
#     root.title("一个经典的GUI程序类的测试")
#     app = Application(master=None)
#
#     root.mainloop()


# from tkinter import *
# from tkinter import messagebox
#
#
# class Application(Frame):
#     """一个经典的GUI程序类的写法"""
#
#     def __init__(self, master):
#         super().__init__(master)  # super代表的是父类的定义，而不是父类对象
#         self.master = master
#         # 几何布局管理器，管理组件的大小和位置
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         """创建组件"""
#         self.label01 = Label(self, text="用户名")
#         self.label01.pack()
#
#         # StringVar变量绑定到指定的组件
#         # StringVar变量的值发生变化，组件内容也发生变化
#         # 组件内容发生变化，StringVar变量的值也发生变化
#         username = StringVar()
#         self.entry01 = Entry(self, textvariable=username)
#         self.entry01.pack()
#         username.set("admin")
#         print(username.get())       # admin
#         print(self.entry01.get())   # admin
#
#         password = StringVar()
#         self.entry02 = Entry(self, textvariable=password, show="*")  # 密码以*显示
#         self.entry02.pack()
#
#         Button(root, text="登录", anchor=E, command=self.login).pack()
#
#
#     def login(self):
#         username = self.entry01.get()
#         password = self.entry02.get()
#         print("去数据库对比用户名密码")
#         print("用户名：" + username)
#         print("密码：" + password)
#         if username == "admin" and password == "123456":
#             messagebox.showinfo("登录系统", "登陆成功")
#         else:
#             messagebox.showinfo("登录系统", "登陆失败，用户名或密码错误")
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("400x250+500+300")
#     root.title("Entry 的测试")
#     app = Application(master=root)
#
#     root.mainloop()

"""测试 Text 多行文本框组件的基本用法，使用面向对象的方式"""

# from tkinter import *
# import webbrowser
#
#
# class Application(Frame):
#     def __init__(self, master=None):
#         super().__init__(master)  # super()代表的是父类的定义，而不是父类对象
#         self.master = master
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         # 宽度 20 个字母(10 个汉字)，高度一个行高
#         self.w1 = Text(root, width=40, height=12, bg="gray")
#         self.w1.pack()
#         self.w1.insert(1.0, "0123456789\nabcdefg")  # 1.0 第一行第一列  行号以 1 开始 列号以 0 开始
#         self.w1.insert(2.3, "锄禾日当午，汗滴禾下土。谁知盘中餐，粒粒皆辛苦\n")
#
#         Button(self, text="重复插入文本", command=self.insertText).pack(side="left")
#         Button(self, text="返回文本", command=self.returnText).pack(side="left")
#         Button(self, text="添加图片", command=self.addImage).pack(side="left")
#         Button(self, text="添加组件", command=self.addWidget).pack(side="left")
#         Button(self, text="通过 tag 精确控制文本", command=self.testTag).pack(side="left")
#
#     def insertText(self):
#         # INSERT 索引表示在光标处插入
#         self.w1.insert(INSERT, ' Gaoqi ')
#         # END 索引号表示在最后插入
#         self.w1.insert(END, '[sxt]')
#         self.w1.insert(1.8, "gaoqi")
#
#     def returnText(self):
#         # Indexes(索引)是用来指向 Text 组件中文本的位置，Text 的组件索引也是对应实际字符之间的位置。
#         # 核心：行号以 1 开始 列号以 0 开始
#         print(self.w1.get(1.2, 1.6))
#         print("所有文本内容：\n" + self.w1.get(1.0, END))
#
#     def addImage(self):
#         # global photo
#         self.photo = PhotoImage(file="../images/logo.gif")
#         self.w1.image_create(END, image=self.photo)
#
#     def addWidget(self):
#         b1 = Button(self.w1, text='爱尚学堂')
#         # 在 text 创建组件的命令
#         self.w1.window_create(INSERT, window=b1)
#
#     def testTag(self):
#         self.w1.delete(1.0, END)
#         self.w1.insert(INSERT, "good good study,day day up!\n 北京尚学堂\n 百战程序员\n百度，搜一下就知道")
#         self.w1.tag_add("good", 1.0, 1.9)
#         self.w1.tag_config("good", background="yellow", foreground="red")  # 改变tag的背景，字体颜色
#         self.w1.tag_add("baidu", 4.0, 4.2)
#         self.w1.tag_config("baidu", underline=True)  # tag加下划线
#         self.w1.tag_bind("baidu", "<Button-1>", self.webshow)  # tag绑定事件
#
#     def webshow(self, event):
#         webbrowser.open("http://www.baidu.com")
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("450x300+200+300")
#     app = Application(master=root)
#     root.mainloop()

# """测试 Radiobutton 组件的基本用法，使用面向对象的方式"""
# from tkinter import *
# from tkinter import messagebox
#
#
# class Application(Frame):
#     def __init__(self, master=None):
#         super().__init__(master)   # super()代表的是父类的定义，而不是父类对象
#         self.master = master
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         self.v = StringVar()
#         self.v.set("F")
#         self.r1 = Radiobutton(self, text="男性", value="M", variable=self.v)
#         self.r2 = Radiobutton(self, text="女性", value="F", variable=self.v)
#         self.r1.pack(side="left")
#         self.r2.pack(side="left")
#         Button(self, text="确定", command=self.confirm).pack(side="left")
#
#     def confirm(self):
#         messagebox.showinfo("测试", "选择的性别:" + self.v.get())
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("400x50+200+300")
#     app = Application(master=root)
#     root.mainloop()

# """测试 Checkbutton 组件的基本用法，使用面向对象的方式"""
# from tkinter import *
# from tkinter import messagebox
#
#
# class Application(Frame):
#     def __init__(self, master=None):
#         super().__init__(master)  # super()代表的是父类的定义，而不是父类对象
#         self.master = master
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         self.codeHobby = IntVar()
#         self.videoHobby = IntVar()
#         print(self.codeHobby.get())  # 默认值是 0
#         self.c1 = Checkbutton(self, text="敲代码", variable=self.codeHobby, onvalue=1, offvalue=0)
#         self.c2 = Checkbutton(self, text="看视频", variable=self.videoHobby, onvalue=1, offvalue=0)
#         self.c1.pack(side="left")
#         self.c2.pack(side="left")
#         Button(self, text="确定", command=self.confirm).pack(side="left")
#
#     def confirm(self):
#         if self.videoHobby.get() == 1:
#             messagebox.showinfo("测试", "看视频，都是正常人有的爱好！你喜欢看什么类型？")
#         if self.codeHobby.get() == 1:
#             messagebox.showinfo("测试", "抓获野生程序猿一只，赶紧送给他尚学堂的视频充饥")
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("400x50+200+300")
#     app = Application(master=root)
#     root.mainloop()

# """测试 Canvas 组件的基本用法，使用面向对象的方式"""
# from tkinter import *
# from tkinter import messagebox
# import random
#
#
# class Application(Frame):
#     def __init__(self, master=None):
#         super().__init__(master)  # super()代表的是父类的定义，而不是父类对象
#         self.master = master
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         self.canvas = Canvas(self, width=300, height=200, bg="green")
#         self.canvas.pack()
#         # 画一条直线
#         line = self.canvas.create_line(10, 10, 30, 20, 40, 50)  # 三个点 (x, y)
#         # 画一个矩形.
#         rect = self.canvas.create_rectangle(50, 50, 100, 100)  # 对角坐标，左上角和右下角坐标
#         # 画一个椭圆.坐标两双。为椭圆的外切矩形左上角和底部右下角
#         oval = self.canvas.create_oval(50, 50, 100, 100)
#         global photo
#         photo = PhotoImage(file="../images/logo.gif")
#         self.canvas.create_image(150, 170, image=photo)
#         Button(self, text="画 10 个矩形", command=self.draw50Recg).pack(side="left")
#
#     def draw50Recg(self):
#         for i in range(0, 10):
#             # 左上角坐标
#             x1 = random.randrange(int(self.canvas["width"]) / 2)
#             y1 = random.randrange(int(self.canvas["height"]) / 2)
#             # 右下角坐标
#             x2 = x1 + random.randrange(int(self.canvas["width"]) / 2)
#             y2 = y1 + random.randrange(int(self.canvas["height"]) / 2)
#             self.canvas.create_rectangle(x1, y1, x2, y2)
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("400x300+200+300")
#     app = Application(master=root)
#     root.mainloop()

"""计算器软件界面的设计"""
# from tkinter import *
# from tkinter import messagebox
# import random
#
#
# class Application(Frame):
#     def __init__(self, master=None):
#         super().__init__(master)    # super()代表的是父类的定义，而不是父类对象
#         self.master = master
#         self.pack()
#         self.createWidget()
#
#     def createWidget(self):
#         """通过 grid 布局实现计算器软件的界面"""
#         btnText = (("MC", "M+", "M-", "MR"),
#                    ("C", "±", "/", "✖"),
#                    (7, 8, 9, "-"),
#                    (4, 5, 6, "+"),
#                    (1, 2, 3, "="),
#                    (0, "."))
#         Entry(self).grid(row=0, column=0, columnspan=4, pady=10)
#         for rindex, r in enumerate(btnText):
#             for cindex, c in enumerate(r):
#                 if c == "=":                      # rowspan跨行，columnspan跨列
#                     Button(self, text=c, width=2)\
#                         .grid(row=rindex + 1, column=cindex, rowspan=2, sticky=EW)
#                 elif c == 0:
#                     Button(self, text=c, width=2)\
#                         .grid(row=rindex + 1, column=cindex, columnspan=2, sticky=EW)
#                 elif c == ".":
#                     Button(self, text=c, width=2)\
#                         .grid(row=rindex + 1, column=cindex+1, sticky=EW)
#                 else:
#                     Button(self, text=c, width=2)\
#                         .grid(row=rindex+1, column=cindex, sticky=EW)
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("200x300+200+300")
#     app = Application(master=root)
#     root.mainloop()

# 测试 pack 布局管理
# from tkinter import *
#
# root = Tk()
# root.geometry("700x220")
# # Frame 是一个矩形区域，就是用来防止其他子组件
# f1 = Frame(root)
# f1.pack()
# f2 = Frame(root)
# f2.pack()
# btnText = ("流行风", "中国风", "日本风", "重金属", "轻音乐")
# for txt in btnText:
#     Button(f1, text=txt).pack(side="left", padx="10")
#     for i in range(1, 20):
#         Button(f2, width=5, height=10, bg="black" if i % 2 == 0 else "white").pack(side="left")
# root.mainloop()

# # coding=utf-8
# from tkinter import *
#
# root = Tk()
# root.geometry("500x300")
# root.title("布局管理 place")
# root["bg"] = "white"
# f1 = Frame(root, width=200, height=200, bg="green")
# f1.place(x=30, y=30)
# Button(root, text="尚学堂").place(relx=0.5, rely=0,
#                                x=100, y=200, relwidth=0.2, relheight=0.2)  # 相对宽度和相对高度
# Button(f1, text="百战程序员").place(relx=0.6, rely=0.7)
# Button(f1, text="高淇老师").place(relx=0.2, rely=0.2)
# root.mainloop()

"""扑克牌游戏的界面设计"""

# from tkinter import *
#
#
# class Application(Frame):
#
#     def __init__(self, master=None):
#         super().__init__(master)  # super()代表的父类的定义，而不是父类对象
#         self.master = master
#         self.place()
#         self.createWidget()
#
#     def createWidget(self):
#         """通过place布局管理器实现扑克牌位置控制"""
#         # 显示一张扑克
#         # self.photo = PhotoImage(file="../images/puke/puke1.gif")
#         # self.puke1 = Label(self.master, image=self.photo)
#         # self.puke1.place(x=10, y=50)
#         # 用列表推导式显示所有图片
#         self.photos = [PhotoImage(file="../images/puke/puke" + str(i+1) + ".gif") for i in range(10)]
#         self.pukes = [Label(self.master, image=self.photos[i]) for i in range(10)]
#
#         for i in range(10):
#             self.pukes[i].place(x=10+i*40, y=50)
#
#         # 为所有Label增加事件处理
#         self.pukes[0].bind_class("Label", "<Button-1>", self.chupai)  # 绑定左键
#
#     def chupai(self, event):
#         print(event.widget.winfo_geometry())
#         print(event.widget.winfo_y())   # 获得y坐标
#
#         if event.widget.winfo_y() == 50:
#             event.widget.place(y=30)
#         else:
#             event.widget.place(y=50)
#
#
# if __name__ == '__main__':
#     root = Tk()
#     root.geometry("600x300+200+300")
#     app = Application(master=root)
#     root.mainloop()


# coding=utf-8
# 测试 command 属性绑定事件，测试 lambda 表达式帮助传参
# from tkinter import *
#
# root = Tk()
# root.geometry("270x50")
#
#
# def mouseTest1():
#     print("command 方式，简单情况：不涉及获取 event 对象，可以使用")
#
#
# def mouseTest2(a, b):
#     print("a={0},b={1}".format(a, b))
#
#
# Button(root, text="测试 command1",
#        command=mouseTest1).pack(side="left")
# Button(root, text="测试 command2",
#        command=lambda: mouseTest2("gaoqi", "xixi")).pack(side="left")
# root.mainloop()

# # coding=utf-8
# # 多种事件绑定方式汇总
# from tkinter import *
#
# root = Tk()
# root.geometry("270x30")
#
#
# def mouseTest1(event):
#     print("bind()方式绑定，可以获取 event 对象")
#     print(event.widget)
#
#
# def mouseTest2(a, b):
#     print("a={0},b={1}".format(a, b))
#     print("command 方式绑定，不能直接获取 event 对象")
#
#
# def mouseTest3(event):
#     print("右键单击事件，绑定给所有按钮啦！！")
#     print(event.widget)
#
#
# b1 = Button(root, text="测试 bind()绑定")
# b1.pack(side="left")
# # bind 方式绑定事件
# b1.bind("<Button-1>", mouseTest1)
# # command 属性直接绑定事件
# b2 = Button(root, text="测试 command2",
#             command=lambda: mouseTest2("gaoqi", "xixi"))
# b2.pack(side="left")
# # 给所有 Button 按钮都绑定右键单击事件<Button-2>
# b1.bind_class("Button", "<Button-2>", mouseTest3)
# root.mainloop()

"""optionmenu 的使用测试"""
# from tkinter import *
#
# root = Tk()
# root.geometry("200x100")
# v = StringVar(root)
# v.set("百战程序员")
# om = OptionMenu(root, v, "尚学堂", "百战程序员", "卓越班[保底 18 万]")
# om["width"] = 10
# om.pack()
#
#
# def test1():
#     print("最喜爱的机构:", v.get())
#
#
# # v.set("尚学堂")    # 直接修改了 optionmenu 中选中的值
# Button(root, text="确定", command=test1).pack()
# root.mainloop()

""" Scale(移动滑块)的使用测试：使用Scale控制字体大小变化"""
# from tkinter import *
#
# root = Tk()
# root.geometry("400x150")
#
#
# def test1(value):
#     print("滑块的值:", value)
#     newFont = ("宋体", value)
#     a.config(font=newFont)
#
#
# s1 = Scale(root, from_=10, to=50, length=200, tickinterval=5, orient=HORIZONTAL, command=test1)
# s1.pack()
# a = Label(root, text="百战程序员", width=10, height=1, bg="black", fg="white")
# a.pack()
# root.mainloop()

"""askcolor 颜色选择框的测试，改变背景色"""
# from tkinter import *
# from tkinter.colorchooser import *
#
# root = Tk()
# root.geometry("400x150")
#
#
# def test1():
#     s1 = askcolor(color="red", title="选择背景色")
#     print(s1)
#     # s1 的值是：((0.0, 0.0, 255.99609375), '#0000ff')
#     root.config(bg=s1[1])
#
#
# Button(root, text="选择背景色", command=test1).pack()
# root.mainloop()

"""文件对话框获取文件"""
# from tkinter import *
# from tkinter.filedialog import *
#
# root = Tk();
# root.geometry("400x100")
#
#
# def test1():
#     f = askopenfilename(title="上传文件",
#                         initialdir="d:/", filetypes=[("视频文件", ".mp4")])
#     # print(f)
#     show["text"] = f
#
#
# Button(root, text="选择编辑的视频文件", command=test1).pack()
# show = Label(root, width=40, height=3, bg="green")
# show.pack()
# root.mainloop()


# coding=utf-8
# askcolor 颜色选择框的测试，改变背景色
# 打开指定 txt 文件，并读出文件内容到窗口
# from tkinter import *
# from tkinter.filedialog import *
#
# root = Tk()
# root.geometry("400x100")
#
#
# def test1():
#     with askopenfile(title="上传文件",
#                      initialdir="d:", filetypes=[("文本文件", ".txt")]) as f:
#         show["text"] = f.read()
#
#
# Button(root, text="选择读取的文本文件", command=test1).pack()
# show = Label(root, width=40, height=3, bg="green")
# show.pack()
# root.mainloop()


"""简单对话框"""
# from tkinter.simpledialog import *
# from tkinter import *
#
# root = Tk()
# root.geometry("400x100")
#
#
# def test1():
#     a = askinteger(title="输入年龄", prompt="请输入年龄", initialvalue=18, minvalue=1, maxvalue=150)
#     # askstring、askfloat 框使用方式一样
#     show["text"] = a
#
#
# Button(root, text="你多大了? 请输入", command=test1).pack()
# show = Label(root, width=40, height=3, bg="green")
# show.pack()
# root.mainloop()

"""简单对话框"""
# from tkinter import *
# from tkinter.messagebox import *
#
# root = Tk()
# root.geometry("400x100")
# a1 = showinfo(title="尚学堂", message="Python400 集从零开始，深入底层，\
#                                       深入算法，打好基础。还手写神经网络")
# print(a1)
# root.mainloop()

"""开发记事本软件的菜单"""
from tkinter import *
from tkinter.filedialog import *
from tkinter.colorchooser import *


class Application(Frame):
    def __init__(self, master=None):
        super().__init__(master)    # super()代表的是父类的定义，而不是父类对象
        self.master = master
        self.textpad = None         # textpad 表示 Text 文本框对象
        self.pack()
        self.createWidget()

    def createWidget(self):
        # 创建主菜单栏
        menubar = Menu(root)
        # 创建子菜单
        menuFile = Menu(menubar)
        menuEdit = Menu(menubar)
        menuHelp = Menu(menubar)
        # 将子菜单加入到主菜单栏
        menubar.add_cascade(label="文件(F)", menu=menuFile)
        menubar.add_cascade(label="编辑(E)", menu=menuEdit)
        menubar.add_cascade(label="帮助(H)", menu=menuHelp)
        # 添加菜单项
        menuFile.add_command(label="新建", accelerator="ctrl+n",
                             command=self.test)
        menuFile.add_command(label="打开", accelerator="ctrl+o",
                             command=self.test)
        menuFile.add_command(label="保存",
                             accelerator="ctrl+s", command=self.test)
        menuFile.add_separator()  # 添加分割线
        menuFile.add_command(label="退出",
                             accelerator="ctrl+q", command=self.test)
        # 将主菜单栏加到根窗口
        root["menu"] = menubar
        # 文本编辑区
        self.textpad = Text(root, width=50, height=30)
        self.textpad.pack()

        # 创建上下文菜单
        self.contextMenu = Menu(root)
        self.contextMenu.add_command(label="背景颜色",  command=self.test)
        # 为右键绑定事件
        root.bind("<Button-3>", self.createContextMenu)

    def test(self):
        pass

    def createContextMenu(self, event):
        # 菜单在鼠标右键单击的坐标显示
        self.contextMenu.post(event.x_root, event.y_root)


if __name__ == '__main__':
    root = Tk()
    root.geometry("450x300+200+300")
    root.title("简易记事本")
    app = Application(master=root)
    root.mainloop()
